package com.crcode.crm.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONObject;

/**
 * 上传公用类
 * 
 * @author cl
 * @date 2019年3月25日 上午
 */
public class MyFileUtil extends Properties {

	private static final long serialVersionUID = 1L;

	public MyFileUtil() {
	}

	private static ConfigUtil config = ConfigUtil.getInstance();// 读取配置文件
	private static String accessoryPath = config.getProperty("contextRoot");// 地址

	/**
	 * 上传文件
	 * 
	 * @author cl
	 * @date 2019年3月25日
	 * @param bytes
	 * @param filePath
	 * @param fileName
	 * @return
	 */
	public static Map<String, Object> uploadFile(byte[] bytes, String filePath, String fileName,String flag) {
		Map<String, Object> map = new HashMap<>();
		String path = accessoryPath + filePath;
		try {
			// 手动写入硬盘
			if (MyFileUtil.makeDir(path)) {
				MyFileUtil.createFile(path, fileName);
			}
			File newFile = new File(path + fileName);
			FileOutputStream fos = new FileOutputStream(newFile, true);
			BufferedOutputStream bos = new BufferedOutputStream(fos);
			bos.write(bytes);
			bos.close();
			fos.close();
			if("COMPLETE".equals(flag)){
				map.put("status", true);
				map.put("info", "上传完成");
				map.put("savePath", filePath+fileName);
			}else{
				map.put("status", true);
				map.put("info", "上传中");
			}
		} catch (IOException e) {
			map.put("status", false);
		}
		return map;
	}
	
	/**
	 * 下载
	 * 
	 * @author cl
	 * @date 2018年9月3日 上午10:33:11
	 * @param path
	 * @throws Exception
	 */
	public static List<Map<String, Object>> download(String path) throws Exception {
		List<Map<String, Object>> list = new ArrayList<>();
		String sourcePath = accessoryPath + path;
		File file = new File(sourcePath);
		if (file.isDirectory()) {
			File files[] = file.listFiles(); // 声明目录下所有的文件 files[];
			for (int i = 0; i < files.length; i++) { // 遍历目录下所有的文件
				String fileName = files[0].getName();
				InputStream inputStream = new FileInputStream(sourcePath + "/" + fileName);
				byte[] bytes = new byte[inputStream.available()];
				inputStream.read(bytes);
				inputStream.close();
				Map<String, Object> map = new HashMap<>();
				map.put("bytes", bytes);
				map.put("fileName", fileName);
				map.put("fileLen", files[0].length());
				list.add(map);
			}
		} else {
			InputStream inputStream = new FileInputStream(sourcePath);
			byte[] bytes = new byte[inputStream.available()];
			inputStream.read(bytes);
			inputStream.close();
			Map<String, Object> map = new HashMap<>();
			String fileName = sourcePath.substring(sourcePath.lastIndexOf("/") + 1);
			map.put("bytes", bytes);
			map.put("fileName", fileName);
			map.put("fileLen", file.length());
			list.add(map);
		}
		return list;
	}
	
	/**
	 * 单一文件下载
	 * @param path
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> downloadFile(String path) throws Exception{
		Map<String, Object> map = new HashMap<>();
		String sourcePath = accessoryPath + path;
		File file = new File(sourcePath);
		InputStream inputStream = new FileInputStream(sourcePath);
		byte[] bytes = new byte[inputStream.available()];
		inputStream.read(bytes);
		inputStream.close();
		String fileName = sourcePath.substring(sourcePath.lastIndexOf("/") + 1);
		map.put("bytes", bytes);
		map.put("fileName", fileName);
		map.put("fileLen", file.length());
		return map;
	}
	
	/**
	 * 打包下载
	 */
	public static Map<String, Object> downloadZip(String path,String fileName) throws Exception {
		Map<String, Object> map = new HashMap<>();
		//图片原图路径
		String picYtPath = accessoryPath + path;
		
		//创建图片及说明的压缩文件
		String zipBasePath = picYtPath.substring(0, picYtPath.lastIndexOf("/"));
		String zipName = fileName+".zip";
		String zipFilePath = zipBasePath + File.separator + zipName;
		//判断这个zip文件是否存在，存在则删除
		File oldZipFile  = new File(zipFilePath);
		if(oldZipFile.exists()){
			MyFileUtil.delAllFile(oldZipFile);
		}
		// 创建需要下载的文件路径的集合
		List<String> filePaths = new ArrayList<String>();
		filePaths.add(picYtPath);
		// 压缩文件
		File zip = new File(zipFilePath);
		if (!zip.exists()) {
			zip.createNewFile();
		}
		// 创建zip文件输出流
		ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
		zipFile(zipBasePath, zipName, zipFilePath, filePaths, zos);
		zos.close();
		
		File zipFile  = new File(zipFilePath);
		InputStream inputStream = new FileInputStream(zipFilePath);
		byte[] bytes = new byte[inputStream.available()];
		inputStream.read(bytes);
		inputStream.close();
		map.put("bytes", bytes);
		map.put("fileName", zipName);
		map.put("fileLen",zipFile.length());
		return map;	
	}
	
	/**
	 * 压缩文件
	 * 
	 * @param zipBasePath
	 *            临时压缩文件基础路径
	 * @param zipName
	 *            临时压缩文件名称
	 * @param zipFilePath
	 *            临时压缩文件完整路径
	 * @param filePaths
	 *            需要压缩的文件路径集合
	 * @throws IOException
	 */
	private static String zipFile(String zipBasePath, String zipName, String zipFilePath, List<String> filePaths,
			ZipOutputStream zos) throws IOException {
		// 循环读取文件路径集合，获取每一个文件的路径
		for (String filePath : filePaths) {
			// 根据文件路径创建文件
			File inputFile = new File(filePath);
			
			// 判断文件是否存在
			if (inputFile.exists()) {
				// 判断是否属于文件，还是文件夹
				if (inputFile.isFile()) {
					// 创建输入流读取文件
					BufferedInputStream bis = new BufferedInputStream(new FileInputStream(inputFile));
					// 将文件写入zip内，即将文件进行打包
					zos.putNextEntry(new ZipEntry(inputFile.getName()));
					// 写入文件的方法，同上
					int size = 0;
					// 设置读取数据缓存大小
					byte[] buffer = new byte[1024];
					while ((size = bis.read(buffer)) > 0) {
						zos.write(buffer, 0, size);
					}
					// 关闭输入输出流
					zos.closeEntry();
					bis.close();
				} else {
					// 如果是文件夹，则使用穷举的方法获取文件，写入zip
					try {
						File[] files = inputFile.listFiles();
						List<String> filePathsTem = new ArrayList<String>();
						for (File fileTem : files) {
							filePathsTem.add(fileTem.toString());
						}
						return zipFile(zipBasePath, zipName, zipFilePath, filePathsTem, zos);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		return null;
	}
	
	/**
	 * 根据文件路径取得文件大小
	 * 
	 * @author cl
	 * @date 2018年8月16日 下午3:37:19
	 * @param filePath
	 * @return
	 */
	public static long getFileSize(String filePath) {
		long size = 0;
		File file = new File(filePath);
		if (file.exists()) {
			size = file.length();
		}
		return size;
	}

	/**
	 * 创建文件 <功能详细描述>
	 * 
	 * @param string
	 * @param string2
	 *            [参数说明]
	 * @return
	 * 
	 * @return void [返回类型说明]
	 * @throws IOException
	 * @exception throws
	 *                [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public static boolean createFile(String path, String fileName) throws IOException {
		boolean creator = true;
		File myPath = new File(path, fileName);
		if (!myPath.exists()) {
			creator = myPath.createNewFile();
		}
		return creator;

	}

	/**
	 * 创建目录 <功能详细描述>
	 * 
	 * @param path
	 * @return [参数说明]
	 * 
	 * @return boolean [返回类型说明]
	 * @exception throws
	 *                [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public static boolean makeDir(String path) {
		boolean mk = true;
		File myPath = new File(path);
		if (!myPath.exists()) {

			mk = myPath.mkdirs();

		}
		return mk;
	}

	/**
	 * 复制单个文件
	 * 
	 * @param oldPath
	 *            String 原文件路径 如：c:/fqf.txt
	 * @param newPath
	 *            String 复制后路径 如：f:/fqf.txt
	 * @return boolean
	 */
	public static void copyFile(String oldPath, String newPath) {
		try {
			(new File(newPath.substring(0, newPath.lastIndexOf("/")))).mkdirs(); // 如果文件夹不存在
																					// 则建立新文件夹
			int byteread = 0;
			File oldfile = new File(oldPath);
			if (oldfile.exists()) { // 文件存在时
				InputStream inStream = new FileInputStream(oldPath); // 读入原文件
				FileOutputStream fs = new FileOutputStream(newPath);
				byte[] buffer = new byte[1444];
				while ((byteread = inStream.read(buffer)) != -1) {
					fs.write(buffer, 0, byteread);
				}
				inStream.close();
				fs.close();
			}
		} catch (Exception e) {
			System.out.println("复制单个文件操作出错");
			e.printStackTrace();
		}
	}
	
	/**
	 * 根据文件路径删除文件或整个文件夹
	 * @author cl  
	 * @date 2019年3月25日 下午
	 * @param path
	 * @return
	 */
	public static Boolean deleteFile(String path) {
		String sourcePath = accessoryPath + path;
		File file=new File(sourcePath);
		delAllFile(file);
		return true;
	}
	
	/**
	 * 根据File删除文件或整个文件夹
	 * 
	 * @param file
	 */
	public static void delAllFile(File file) {
		if (file == null) {
			return;
		} else if (file.exists()) {// 如果此抽象指定的对象存在并且不为空。
			if (file.isFile()) {
				file.delete();// 如果此抽象路径代表的是文件，直接删除。
				delPatrentFile(file);//删除上级
			} else if (file.isDirectory()) {// 如果此抽象路径指代的是目录
				String[] str = file.list();// 得到目录下的所有路径
				if (str == null) {
					file.delete();// 如果这个目录下面是空，则直接删除
				} else {// 如果目录不为空，则遍历名字，得到此抽象路径的字符串形式。
					for (String st : str) {
						delAllFile(new File(file, st));
					} // 遍历清楚所有当前文件夹里面的所有文件。
					file.delete();// 清楚文件夹里面的东西后再来清楚这个空文件夹
				}
			}
		}
	}
	
	/**
	 * 如果父级目录为空文件夹
	 * @author cl  
	 * @date 2018年11月9日 下午2:32:16
	 * @param file
	 */
	public static void delPatrentFile(File file) {
		String filePath=file.getPath();
		filePath=filePath.substring(0, filePath.lastIndexOf("\\"));
		File parentFile = new File(filePath); 
		if(parentFile.isDirectory()){
			String[] str = parentFile.list();// 得到目录下的所有路径
			if (str.length==0) {
				parentFile.delete();
			} else{
				return;
			}
			delPatrentFile(parentFile);
		}
	}

	/**
	 * 根据文件路径和名字删除单个文件
	 * 
	 * @param filePathAndName
	 *            String 文件路径及名称 如c:/fqf.txt
	 * @param fileContent
	 *            String
	 * @return boolean
	 */
	public static void delFile(String filePathAndName) {
		try {
			String filePath = filePathAndName;
			filePath = filePath.toString();
			java.io.File myDelFile = new java.io.File(filePath);
			myDelFile.delete();

		} catch (Exception e) {
			System.out.println("删除文件操作出错");
			e.printStackTrace();

		}

	}
	
	public static void exp(HttpServletRequest request,HttpServletResponse response,String datas) throws IOException {
		ExportExcelXTsts ee=new ExportExcelXTsts();
		//获取要导出的数据
		JSONObject obj=JSONObject.parseObject(datas);
		//获取日志用参数
		OutputStream out = null;
		// 设置要下载文件的文件名称
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
		String dateString = formatter.format(currentTime);
		//设置文件标题
		String wjtitle = "";
		String type=obj.getString("type");
		if("enter".equals(type)){
			wjtitle = "企业数据";
		}else if("project".equals(type)){
			wjtitle = "项目数据";
		}else if("log".equals(type)){
			wjtitle = "日志数据";
		}
		//后端处理浏览器版本
		String filename=wjtitle+dateString+ ".xls";
		String getHeader=request.getHeader("User-Agent").toLowerCase();
		if (getHeader.indexOf("firefox") > 0) {    
			filename = new String(filename.getBytes("UTF-8"), "ISO8859-1"); // firefox浏览器    
	    }else if (getHeader.indexOf("CHROME") > 0 && getHeader.indexOf("EDGE")==-1) {    
	    	filename = new String(filename.getBytes("UTF-8"), "ISO8859-1");// 谷歌    
		}else{
			filename = URLEncoder.encode(filename, "UTF-8");// IE浏览器    
		}  
		//设置文件名
		response.addHeader("Content-Disposition", "attachment;filename="+filename);
		response.setContentType("application/vnd.ms-excel");// 指明response的返回对象是文件流
		out = response.getOutputStream();
		//导出excel
		ee.exportExcel(out,obj,wjtitle);
		out.close();
	}
}
